package com.redis.service.impl;

import cn.hutool.json.JSONUtil;
import com.redis.model.User;
import com.redis.service.RedisService;
import com.redis.utils.RedisSortSet;
import com.redis.utils.RedisStrings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Redis业务类
 * @author YI
 * @date 2018-4-8 16:17:27
 */
@Service
public class RedisServiceImpl implements RedisService {
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    RedisStrings redisStrings;
    @Autowired
    RedisSortSet redisSortSet;


    /**
     * 用于地理信息 添加一个ZSET的结构 CHINA:CITY
     */
    public static String key = "CHINA:CITY";

    /**
     * 保存数据到Redis中
     * @param key
     * @param value
     */
    @Override
    public void save(String key, String value) {
        redisStrings.set(key, JSONUtil.toJsonPrettyStr(value));
    }

    @Override
    public List redisGeo() {
        List<Object> geoList = new ArrayList<>();

        //用于地理信息 添加一个ZSET的结构 CHINA:CITY
        BoundGeoOperations boundGeoOperations = redisTemplate.boundGeoOps(key);
        //南京市 118.803805,32.060168
        Point nanjing = new Point(118.803805,32.060168);
        //北京市 116.397039,39.9077
        Point beijing = new Point(116.397039,39.9077);
        //天津市 116.397039,39.9077
        Point tianjing = new Point(117.20,39.12);

        //添加地理信息到Redis
        System.out.println(boundGeoOperations.add(nanjing, "南京市"));
        System.out.println(boundGeoOperations.add(beijing, "北京市"));
        System.out.println(boundGeoOperations.add(tianjing, "天津市"));

        //获取某个地理位置的geohash值
        List<String> list = boundGeoOperations.hash("南京市");
        geoList.add("南京市的geoHash = " + list.get(0));

        //获取某个地理位置的坐标
        List<Point> pointList = boundGeoOperations.position("南京市");
        geoList.add("南京市的经纬度为 = " + pointList.get(0));

        //获取两个地理位置的距离
        Distance distance = boundGeoOperations.distance("南京市", "天津市", Metrics.KILOMETERS);
        geoList.add("南京市到天津市之间的距离是：" + distance.getValue() + "km");

        //根据给定地理位置坐标获取指定范围内的地理位置集合
        //查询南京市1000KM范围内的城市
        Circle within = new Circle(nanjing,1000000);
        //设置geo查询参数
        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        //查询返回结果包括距离和坐标
        geoRadiusArgs = geoRadiusArgs.includeCoordinates().includeDistance();
        //按查询出的坐标距离中心坐标的距离进行排序
        geoRadiusArgs.sortAscending();
        //限制查询返回的数量
        geoRadiusArgs.limit(5);
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = boundGeoOperations.radius(within,geoRadiusArgs);
        List<GeoResult<RedisGeoCommands.GeoLocation<String>>> geoResultList = geoResults.getContent();
        for (GeoResult geoResult : geoResultList) {
            geoList.add("geoRadius  " + geoResult.getContent());
        }

        //根据给定地理位置获取指定范围内的地理位置集合 查询南京市800KM范围内的城市
        geoResults = boundGeoOperations.radius("南京市",new Distance(800000), geoRadiusArgs);
        geoResultList = geoResults.getContent();
        for (GeoResult geoResult : geoResultList) {
            geoList.add("radius  " + geoResult.getContent());
        }

        //删除位置信息,此命令不是geo提供的，是使用zrem命令删除的
//        System.out.println(boundGeoOperations.remove("南京市"));

        return geoList;
    }

    @Override
    public List sortSet() {
        List<User> list = new ArrayList<>();

        User user1 = new User("12345", "张三", 99.9);
        User user2 = new User("12346", "李四", 99.8);
        User user3 = new User("12347", "王五", 96.8);
        User user4 = new User("12348", "赵六", 98.8);
        User user5 = new User("12349", "貂蝉", 99.6);
        User user6 = new User("12350", "西施", 99.0);
        User user7 = new User("12351", "玉环", 100.0);
        User user8 = new User("12352", "昭君", 99.6);

        redisSortSet.zadd("game", user1.getScore(), JSONUtil.toJsonStr(user1));
        redisSortSet.zadd("game", user2.getScore(), JSONUtil.toJsonStr(user2));
        redisSortSet.zadd("game", user3.getScore(), JSONUtil.toJsonStr(user3));
        redisSortSet.zadd("game", user4.getScore(), JSONUtil.toJsonStr(user4));
        redisSortSet.zadd("game", user5.getScore(), JSONUtil.toJsonStr(user5));
        redisSortSet.zadd("game", user6.getScore(), JSONUtil.toJsonStr(user6));
        redisSortSet.zadd("game", user7.getScore(), JSONUtil.toJsonStr(user7));
        redisSortSet.zadd("game", user8.getScore(), JSONUtil.toJsonStr(user8));

        // 根据权重排序
        Set<String> game = redisSortSet.zrevrange("game", 0, -1);

        Iterator<String> iterator = game.iterator();
        int rank = 1;
        while (iterator.hasNext()){
            User user = JSONUtil.toBean(iterator.next(), User.class);
            user.setRank(rank++);
            list.add(user);
            System.out.println(user);
        }

        return list;
    }
}
